package tracing

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"time"

	"baseService/internal/infrastructure/config"
	"baseService/internal/pkg/logger"

	"github.com/gin-gonic/gin"
)

// Middleware 链路追踪中间件（简化版）
// 对于中小项目，一个请求ID足够了，不需要复杂的分布式追踪
type Middleware struct {
	config *config.TracingConfig
	logger logger.Logger
}

// NewMiddleware 创建链路追踪中间件
func NewMiddleware(config *config.TracingConfig, logger logger.Logger) *Middleware {
	return &Middleware{
		config: config,
		logger: logger,
	}
}

// Handler 中间件处理函数
func (m *Middleware) Handler() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 如果未启用，直接通过
		if !m.config.Enable {
			c.Next()
			return
		}

		// 检查是否在跳过路径中
		if m.shouldSkipPath(c.Request.URL.Path) {
			c.Next()
			return
		}

		// 获取或生成请求ID
		requestID := c.GetHeader(m.config.TraceIDHeader)
		if requestID == "" {
			requestID = m.generateRequestID()
		}

		// 设置到上下文和响应头
		c.Set("request_id", requestID)
		c.Header(m.config.TraceIDHeader, requestID)

		// 注入带 request_id 的日志实例，方便后续使用
		logger.InjectContextLogger(c, m.logger.WithRequestID(c))

		// 记录请求开始
		startTime := time.Now()
		m.logger.Infof("请求开始 - request_id: %s, method: %s, path: %s, ip: %s",
			requestID,
			c.Request.Method,
			c.Request.URL.Path,
			c.ClientIP())

		// 处理请求
		c.Next()

		// 记录请求完成
		duration := time.Since(startTime)
		statusCode := c.Writer.Status()

		logMsg := "请求完成 - request_id: %s, method: %s, path: %s, status: %d, duration: %dms, ip: %s"
		if statusCode >= 500 {
			m.logger.Errorf(logMsg,
				requestID,
				c.Request.Method,
				c.Request.URL.Path,
				statusCode,
				duration.Milliseconds(),
				c.ClientIP())
		} else if statusCode >= 400 {
			m.logger.Warnf(logMsg,
				requestID,
				c.Request.Method,
				c.Request.URL.Path,
				statusCode,
				duration.Milliseconds(),
				c.ClientIP())
		} else {
			m.logger.Infof(logMsg,
				requestID,
				c.Request.Method,
				c.Request.URL.Path,
				statusCode,
				duration.Milliseconds(),
				c.ClientIP())
		}
	}
}

// shouldSkipPath 检查是否应该跳过该路径
func (m *Middleware) shouldSkipPath(path string) bool {
	for _, skipPath := range m.config.SkipPaths {
		if path == skipPath {
			return true
		}
		// 简单的后缀匹配（如 *.css）
		if len(skipPath) > 2 && skipPath[0] == '*' && skipPath[1] == '.' {
			suffix := skipPath[1:]
			if len(path) > len(suffix) && path[len(path)-len(suffix):] == suffix {
				return true
			}
		}
	}
	return false
}

// generateRequestID 生成请求ID
func (m *Middleware) generateRequestID() string {
	// 使用 crypto/rand 生成安全的随机ID
	// 格式: req_16位十六进制 (如: req_a1b2c3d4e5f67890)
	b := make([]byte, 8)
	_, err := rand.Read(b)
	if err != nil {
		// fallback: 使用时间戳
		return fmt.Sprintf("req_%d", time.Now().UnixNano())
	}
	return "req_" + hex.EncodeToString(b)
}

// GetRequestID 从上下文获取请求ID（工具函数）
func GetRequestID(c *gin.Context) string {
	if requestID, exists := c.Get("request_id"); exists {
		if id, ok := requestID.(string); ok {
			return id
		}
	}
	return ""
}
